﻿using Microsoft.AspNetCore.Http;
using System.Linq.Expressions;
using System.Reflection;

namespace Infrastructure.Http
{
    public static class HttpContextLocal
    {
        // 静态字段，用于缓存创建的委托，提高性能
        private static Func<object> _asyncLocalAccessor;
        private static Func<object, object> _holderAccessor;
        private static Func<object, HttpContext> _httpContextAccessor;

        // 获取当前 HTTP 上下文的静态方法
        public static HttpContext Current()
        {
            // 获取 AsyncLocal<> 实例
            object obj = (_asyncLocalAccessor ?? (_asyncLocalAccessor = CreateAsyncLocalAccessor()))();
            if (obj == null)
            {
                return null;
            }

            // 获取 AsyncLocal<> 实例中的值
            object obj2 = (_holderAccessor ?? (_holderAccessor = CreateHolderAccessor(obj)))(obj);
            if (obj2 == null)
            {
                return null;
            }

            // 获取 HttpContext 对象
            return (_httpContextAccessor ?? (_httpContextAccessor = CreateHttpContextAccessor(obj2)))(obj2);
        }

        // 使用表达式树创建委托，用于获取 AsyncLocal<> 实例
        private static Func<object> CreateAsyncLocalAccessor()
        {
            // 获取 HttpContextAccessor 类的私有静态字段 _httpContextCurrent
            FieldInfo field = typeof(HttpContextAccessor).GetField("_httpContextCurrent", BindingFlags.Static | BindingFlags.NonPublic);
            MemberExpression body3 = Expression.Field(null, field);
            // 返回一个委托，用于获取 _httpContextCurrent 的值
            return Expression.Lambda<Func<object>>(body3, Array.Empty<ParameterExpression>()).Compile();
        }

        // 使用表达式树创建委托，用于从 AsyncLocal<> 实例中获取值
        private static Func<object, object> CreateHolderAccessor(object asyncLocal)
        {
            // 获取 AsyncLocal<> 的泛型参数类型
            Type type = asyncLocal.GetType().GetGenericArguments()[0];
            // 获取 AsyncLocal<> 的 Value 属性的 Getter 方法
            MethodInfo getMethod = typeof(AsyncLocal<>).MakeGenericType(type).GetProperty("Value").GetGetMethod();
            ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object));
            UnaryExpression instance = Expression.Convert(parameterExpression2, asyncLocal.GetType());
            // 调用 AsyncLocal<> 的 Value 属性的 Getter 方法
            MethodCallExpression body2 = Expression.Call(instance, getMethod);
            // 返回一个委托，用于获取 AsyncLocal<> 的值
            return Expression.Lambda<Func<object, object>>(body2, new ParameterExpression[1] { parameterExpression2 }).Compile();
        }

        // 使用表达式树创建委托，用于从 holder 对象中获取 HttpContext 对象
        private static Func<object, HttpContext> CreateHttpContextAccessor(object holder)
        {
            // 获取 holder 对象的 Context 字段
            ParameterExpression parameterExpression = Expression.Parameter(typeof(object));
            UnaryExpression expression = Expression.Convert(parameterExpression, holder.GetType());
            MemberExpression expression2 = Expression.Field(expression, "Context");
            // 将 Context 字段转换为 HttpContext 类型
            UnaryExpression body = Expression.Convert(expression2, typeof(HttpContext));
            // 返回一个委托，用于获取 HttpContext 对象
            return Expression.Lambda<Func<object, HttpContext>>(body, new ParameterExpression[1] { parameterExpression }).Compile();
        }
    }
}
